#include "threadpool.h"
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

/**
 * @brief 工作线程函数
 *
 * @param arg 线程池指针
 * @return void* 总是返回NULL
 *
 * 工作线程的主要循环：
 * 1. 等待任务或关闭信号
 * 2. 从任务队列中取出任务
 * 3. 执行任务
 * 4. 循环直到线程池关闭且任务队列为空
 */
static void *thread_worker(void *arg)
{
    ThreadPool *pool = (ThreadPool *)arg;

    while (1)
    {
        pthread_mutex_lock(&pool->mutex);

        // 等待条件：线程池未关闭且任务队列为空
        while (!pool->shutdown && pool->task_queue_head == NULL)
        {
            pthread_cond_wait(&pool->cond, &pool->mutex);
        }

        // 检查终止条件：线程池关闭且无任务
        if (pool->shutdown && pool->task_queue_head == NULL)
        {
            pthread_mutex_unlock(&pool->mutex);
            pthread_exit(NULL); // 安全退出线程
        }

        // 从任务队列头部取出任务
        Task *task = pool->task_queue_head;
        pool->task_queue_head = task->next;
        pool->task_count--; // 更新任务计数

        // 如果队列已空，更新尾指针
        if (pool->task_queue_head == NULL)
        {
            pool->task_queue_tail = NULL;
        }

        pthread_mutex_unlock(&pool->mutex); // 释放锁

        // 执行任务（在锁外执行，避免阻塞其他线程）
        task->function(task->arg);
        free(task); // 释放任务内存
    }
    return NULL;
}

/**
 * @brief 创建线程池
 *
 * @param thread_count 工作线程数量
 * @return ThreadPool* 成功返回线程池指针，失败返回NULL
 *
 * 创建步骤：
 * 1. 参数校验
 * 2. 分配线程池内存
 * 3. 初始化同步原语（互斥锁和条件变量）
 * 4. 创建工作线程数组
 * 5. 创建工作线程
 * 6. 设置线程池状态
 */
ThreadPool *thread_pool_create(int thread_count)
{
    // 参数校验
    if (thread_count <= 0)
    {
        errno = EINVAL; // 设置错误码
        return NULL;
    }

    // 分配线程池内存
    ThreadPool *pool = calloc(1, sizeof(ThreadPool));
    if (!pool)
        goto error;

    // 初始化互斥锁
    if (pthread_mutex_init(&pool->mutex, NULL) != 0)
    {
        goto error;
    }

    // 初始化条件变量
    if (pthread_cond_init(&pool->cond, NULL) != 0)
    {
        goto mutex_error;
    }

    // 创建工作线程数组
    pool->threads = malloc(thread_count * sizeof(pthread_t));
    if (!pool->threads)
    {
        goto cond_error;
    }

    // 初始化线程池状态
    pool->thread_count = thread_count;
    pool->shutdown = false;
    pool->started = true;
    pool->task_count = 0;

    // 创建工作线程
    for (int i = 0; i < thread_count; i++)
    {
        if (pthread_create(&pool->threads[i], NULL, thread_worker, pool) != 0)
        {
            // 创建失败：设置关闭标志并唤醒所有线程
            pool->shutdown = true;
            pthread_cond_broadcast(&pool->cond);

            // 等待已创建线程退出
            for (int j = 0; j < i; j++)
            {
                pthread_join(pool->threads[j], NULL);
            }
            goto threads_error;
        }
    }
    return pool;

// 错误处理链（按资源分配逆序释放）
threads_error:
    free(pool->threads);
cond_error:
    pthread_cond_destroy(&pool->cond);
mutex_error:
    pthread_mutex_destroy(&pool->mutex);
error:
    free(pool);
    return NULL;
}

/**
 * @brief 向线程池添加任务
 *
 * @param pool 线程池实例
 * @param task_func 任务函数指针
 * @param arg 传递给任务函数的参数
 * @return bool 成功返回true，失败返回false
 *
 * 添加任务步骤：
 * 1. 参数校验
 * 2. 创建任务结构体
 * 3. 加锁访问任务队列
 * 4. 将任务添加到队列尾部
 * 5. 唤醒等待线程
 */
bool thread_pool_add_task(ThreadPool *pool, void *(*task_func)(void *), void *arg)
{
    // 参数校验
    if (!pool || !task_func || pool->shutdown)
    {
        errno = EINVAL;
        return false;
    }

    // 创建新任务
    Task *new_task = malloc(sizeof(Task));
    if (!new_task)
        return false;

    // 初始化任务
    new_task->function = task_func;
    new_task->arg = arg;
    new_task->next = NULL;

    pthread_mutex_lock(&pool->mutex);

    // 添加到任务队列
    if (pool->task_queue_tail)
    {
        // 队列非空：添加到尾部
        pool->task_queue_tail->next = new_task;
    }
    else
    {
        // 队列为空：设置为头节点
        pool->task_queue_head = new_task;
    }
    pool->task_queue_tail = new_task;
    pool->task_count++; // 更新任务计数

    // 通知一个等待的工作线程
    pthread_cond_signal(&pool->cond);
    pthread_mutex_unlock(&pool->mutex);
    return true;
}

/**
 * @brief 销毁线程池
 *
 * @param pool 线程池实例指针
 *
 * 销毁步骤：
 * 1. 设置关闭标志
 * 2. 唤醒所有工作线程
 * 3. 等待所有线程退出
 * 4. 清理剩余任务
 * 5. 释放所有资源
 */
void thread_pool_destroy(ThreadPool *pool)
{
    // 检查无效输入或已销毁的线程池
    if (!pool || !pool->started)
        return;

    pthread_mutex_lock(&pool->mutex);
    pool->shutdown = true; // 设置关闭标志
    pthread_mutex_unlock(&pool->mutex);

    // 唤醒所有工作线程
    pthread_cond_broadcast(&pool->cond);

    // 等待所有工作线程退出
    for (int i = 0; i < pool->thread_count; i++)
    {
        pthread_join(pool->threads[i], NULL);
    }

    // 清理未完成的任务
    Task *task;
    while (pool->task_queue_head)
    {
        task = pool->task_queue_head;
        pool->task_queue_head = task->next;
        free(task);
    }

    // 释放资源
    free(pool->threads);
    pthread_mutex_destroy(&pool->mutex);
    pthread_cond_destroy(&pool->cond);
    free(pool);
}